package com.finalterm.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.finalterm.common.result.Result;
import com.finalterm.order.entity.CompensationTask;
import com.finalterm.order.feign.ProductServiceClient;
import com.finalterm.order.mapper.CompensationTaskMapper;
import com.finalterm.order.service.CompensationTaskService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 补偿任务服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CompensationTaskServiceImpl implements CompensationTaskService {
    
    private final CompensationTaskMapper compensationTaskMapper;
    private final ProductServiceClient productServiceClient;
    
    // 最大重试次数
    private static final int MAX_RETRY_COUNT = 5;
    // 重试间隔（分钟）
    private static final int[] RETRY_INTERVALS = {5, 10, 30, 60, 120}; // 5分钟、10分钟、30分钟、1小时、2小时
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createStockRecoverTask(String orderNo, Long productId, Integer quantity) {
        // 检查是否已存在相同的补偿任务
        LambdaQueryWrapper<CompensationTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompensationTask::getTaskType, "STOCK_RECOVER")
               .eq(CompensationTask::getOrderNo, orderNo)
               .eq(CompensationTask::getProductId, productId)
               .in(CompensationTask::getStatus, "PENDING", "SUCCESS");
        
        CompensationTask existTask = compensationTaskMapper.selectOne(wrapper);
        if (existTask != null) {
            if ("SUCCESS".equals(existTask.getStatus())) {
                log.info("订单{}的库存恢复补偿任务已成功完成，跳过创建", orderNo);
                return;
            }
            if ("PENDING".equals(existTask.getStatus())) {
                log.info("订单{}的库存恢复补偿任务已存在，跳过创建", orderNo);
                return;
            }
        }
        
        CompensationTask task = new CompensationTask();
        task.setTaskType("STOCK_RECOVER");
        task.setOrderNo(orderNo);
        task.setProductId(productId);
        task.setQuantity(quantity);
        task.setStatus("PENDING");
        task.setRetryCount(0);
        task.setMaxRetryCount(MAX_RETRY_COUNT);
        task.setNextRetryTime(LocalDateTime.now().plusMinutes(RETRY_INTERVALS[0])); // 5分钟后首次重试
        task.setCreateTime(LocalDateTime.now());
        task.setUpdateTime(LocalDateTime.now());
        
        compensationTaskMapper.insert(task);
        log.info("创建库存恢复补偿任务成功，订单号：{}，商品ID：{}，数量：{}", orderNo, productId, quantity);
    }
    
    @Override
    public void processPendingTasks() {
        // 查询需要重试的任务，每次处理10个
        List<CompensationTask> pendingTasks = compensationTaskMapper.selectPendingTasks(LocalDateTime.now(), 10);
        
        if (pendingTasks.isEmpty()) {
            log.debug("没有需要处理的补偿任务");
            return;
        }
        
        log.info("开始处理{}个待重试的补偿任务", pendingTasks.size());
        
        for (CompensationTask task : pendingTasks) {
            try {
                boolean success = executeTask(task);
                if (success) {
                    updateTaskStatus(task.getId(), "SUCCESS", null);
                    log.info("补偿任务执行成功，任务ID：{}，订单号：{}", task.getId(), task.getOrderNo());
                } else {
                    incrementRetryCount(task.getId(), "库存恢复调用失败");
                    log.warn("补偿任务执行失败，任务ID：{}，订单号：{}", task.getId(), task.getOrderNo());
                }
            } catch (Exception e) {
                incrementRetryCount(task.getId(), "执行异常：" + e.getMessage());
                log.error("补偿任务执行异常，任务ID：{}，订单号：{}，异常：{}", 
                         task.getId(), task.getOrderNo(), e.getMessage(), e);
            }
        }
    }
    
    @Override
    public boolean executeTask(CompensationTask task) {
        if (!"STOCK_RECOVER".equals(task.getTaskType())) {
            log.warn("不支持的任务类型：{}", task.getTaskType());
            return false;
        }
        
        try {
            // 调用商品服务恢复库存
            Result<Boolean> result = productServiceClient.recoverStock(
                    task.getProductId(), task.getQuantity(), task.getOrderNo());
            
            if (result.getCode() == 200 && result.getData() != null && result.getData()) {
                log.info("补偿任务库存恢复成功，订单号：{}，商品ID：{}，数量：{}", 
                        task.getOrderNo(), task.getProductId(), task.getQuantity());
                return true;
            } else {
                log.warn("补偿任务库存恢复失败，订单号：{}，响应：{}", task.getOrderNo(), result.getMessage());
                return false;
            }
        } catch (Exception e) {
            log.error("补偿任务执行异常，订单号：{}，异常：{}", task.getOrderNo(), e.getMessage());
            return false;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTaskStatus(Long taskId, String status, String failureReason) {
        CompensationTask task = new CompensationTask();
        task.setId(taskId);
        task.setStatus(status);
        task.setFailureReason(failureReason);
        task.setUpdateTime(LocalDateTime.now());
        
        compensationTaskMapper.updateById(task);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void incrementRetryCount(Long taskId, String failureReason) {
        CompensationTask task = compensationTaskMapper.selectById(taskId);
        if (task == null) {
            log.warn("补偿任务不存在，任务ID：{}", taskId);
            return;
        }
        
        int newRetryCount = task.getRetryCount() + 1;
        
        if (newRetryCount >= task.getMaxRetryCount()) {
            // 达到最大重试次数，标记为失败
            task.setStatus("FAILED");
            task.setFailureReason("达到最大重试次数：" + failureReason);
            task.setNextRetryTime(null);
            log.warn("补偿任务达到最大重试次数，标记为失败，任务ID：{}，订单号：{}", taskId, task.getOrderNo());
        } else {
            // 设置下次重试时间
            int intervalIndex = Math.min(newRetryCount - 1, RETRY_INTERVALS.length - 1);
            LocalDateTime nextRetryTime = LocalDateTime.now().plusMinutes(RETRY_INTERVALS[intervalIndex]);
            
            task.setNextRetryTime(nextRetryTime);
            task.setFailureReason(failureReason);
            log.info("补偿任务重试次数增加，任务ID：{}，当前重试次数：{}，下次重试时间：{}", 
                    taskId, newRetryCount, nextRetryTime);
        }
        
        task.setRetryCount(newRetryCount);
        task.setUpdateTime(LocalDateTime.now());
        
        compensationTaskMapper.updateById(task);
    }
}
